home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / LOADER / LOADER.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  12KB  |  467 lines

  1. /*****************************************************************************
  2.  * FILE: loader.c                                 *
  3.  *                                         *
  4.  * DESC: loader for 32bit RSX compiled with EMX/GCC                 *
  5.  *                                         *
  6.  * Copyright (C) 1994                                 *
  7.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  8.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  9.  *                                         *
  10.  * See the files "README" and "COPYING" for further copyright and warranty   *
  11.  * information.                                  *
  12.  *                                         *
  13.  *****************************************************************************/
  14.  
  15. #include <dos.h>
  16. #include "LOADER.H"
  17.  
  18. struct info {
  19.     unsigned long  membytes;
  20.     unsigned long  memaddress;
  21.     unsigned long  text_start;
  22.     unsigned long  data_start;
  23.     unsigned long  bss_start;
  24.     unsigned long  stack_start;
  25.     unsigned long  init_brk;
  26.     unsigned long  entry;
  27.     unsigned short code16sel;
  28.     unsigned short data16sel;
  29. } info;
  30.  
  31. extern unsigned _psp;
  32.  
  33. WORD code32sel;         /* RSX CS selector */
  34. WORD data32sel;         /* RSX DS selector */
  35. DWORD stackp32;         /* RSX satck pointer */
  36.  
  37. static void far *extdata;    /* DOS memory for RSX */
  38. static unsigned segm;        /* segment address */
  39. static char far * env_str;    /* env far pointer */
  40. static char cline[260];     /* arguments */
  41.  
  42. static int n_strlen(char *str)
  43. {
  44.     char *s;
  45.     for (s = str; *s; ++s);
  46.     return (s - str);
  47. }
  48.  
  49. static int f_strlen(char far *str)
  50. {
  51.     char far *s;
  52.     for (s = str; *s; ++s);
  53.     return ((int)(char near *)s - (int)(char near *)str);
  54. }
  55.  
  56. static char *my_strcpy(char *string1, char *string2)
  57. {
  58.     char *dst = string1;
  59.     while ((*dst = *string2) != 0)
  60.     ++dst, ++string2;
  61.     return (string1);
  62. }
  63.  
  64. static void error(char *s)
  65. {
  66.     dos_puts("loader v1.0 : (c) Rainer Schnitker\n\r$");
  67.     dos_puts("rsx_32 loader error: $");
  68.     dos_puts(s);
  69. }
  70.  
  71. static int skip_exe_hdr(int filehandle, DWORD * headoff)
  72. {
  73.     struct exe_hdr exehdr;
  74.  
  75.     exehdr.signatur = 0;
  76.     dos_read(filehandle, &exehdr, sizeof(WORD) * 3);
  77.  
  78.     if (exehdr.signatur == 0x5a4d) {    /* falls exe-kopf */
  79.     *headoff += (DWORD) exehdr.high * 512L;
  80.     if (exehdr.low)
  81.         *headoff += (DWORD) exehdr.low - 512L;
  82.     }
  83.     if (dos_lseek(filehandle, *headoff, SEEK_SET) != -1L)
  84.     return 0;
  85.     else {
  86.     *headoff = 0;
  87.     dos_lseek(filehandle, 0, SEEK_SET);
  88.     return -1;
  89.     }
  90. }
  91.  
  92. static int argvenv(int argc, char **argv)
  93. {
  94.     DWORD far * vectors;        /* building argv, env    */
  95.     WORD len;                /* current len of string */
  96.     WORD stkp;                /* current stack pos     */
  97.     WORD count = 3;            /* 0=argc 1=argv 2=env   */
  98.     int i, envc = 0;
  99.     static char npx_str[] = "RSX_x87=?";
  100.  
  101.     /* instead allocate memory, take some EMX space at DS:0x8000 */
  102.     vectors = (DWORD far *) (((DWORD)segm << 16) | 0x8000);
  103.  
  104.     /* EMX program stack pointer */
  105.     /* stack grows down from DS:0xFFFC */
  106.     stkp = (WORD) stackp32;
  107.     FP_SEG(extdata) = segm;
  108.     FP_OFF(extdata) = stkp;
  109.  
  110.     /* store env strings in user stack, built vectors */
  111.     for (; *env_str; ) {
  112.     len = f_strlen(env_str) + 1;
  113.     stkp -= len;
  114.     stkp &= ~3;
  115.     FP_OFF(extdata) = stkp;
  116.     far_memcpy(extdata, env_str, len);
  117.     vectors[count++] = (DWORD) stkp;
  118.     env_str += len;
  119.     envc ++;
  120.     }
  121.     /* put 387 status on env */
  122.     i = npx_installed();
  123.     npx_str[8] = (char) i + '0';
  124.     len = sizeof(npx_str) + 1;
  125.     stkp -= len;
  126.     stkp &= ~3;
  127.     FP_OFF(extdata) = stkp;
  128.     far_memcpy(extdata, (char far *)npx_str, len);
  129.     vectors[count++] = (DWORD) stkp;
  130.     env_str += len;
  131.     envc ++;
  132.  
  133.     vectors[count++] = 0L;     /* last is a NULL pointer */
  134.  
  135.     /* store arg strings in user stack, built vectors */
  136.     for (i = 0; i < argc; i++) {
  137.     len = f_strlen(argv[i]) + 1;
  138.     stkp -= len;
  139.     stkp &= ~3;
  140.     FP_OFF(extdata) = stkp;
  141.     far_memcpy(extdata, (void far *) argv[i], len);
  142.     vectors[count] = (DWORD) stkp;
  143.     count++;
  144.     }
  145.     vectors[count++] = 0L;     /* last is a NULL pointer */
  146.  
  147.     len = count * sizeof(long);
  148.     stkp -= len;
  149.     vectors[0] = argc;
  150.     vectors[1] = stkp + (4 + envc) * sizeof(long);  /* & vectors[3+nenvp+1] */
  151.     vectors[2] = stkp + 3 * sizeof(long);        /* & vectors[3] */
  152.     FP_OFF(extdata) = stkp;
  153.     far_memcpy(extdata, vectors, len);
  154.  
  155.     stackp32 = stkp;            /* save current pos! (for entry) */
  156.     stackp32 += 3 * sizeof(long);
  157.     return 0;
  158. }
  159.  
  160.  
  161. static int read_in(int fhandle, DWORD address, long size)
  162. {
  163. #define READ_MAX 0xFF00
  164.  
  165.     void far *dosmemp;
  166.     WORD word_size;
  167.  
  168.     FP_OFF(dosmemp) = 0;
  169.  
  170.     while (size != 0L) {
  171.     FP_SEG(dosmemp) = (WORD) (address >> 4);
  172.     word_size = (size >> 16) ? READ_MAX : (WORD) size;
  173.     dos_read_far(fhandle, dosmemp, word_size);
  174.     address += (DWORD) READ_MAX;
  175.     size -= (DWORD) word_size;
  176.     }
  177.  
  178.     return 0;
  179. }
  180.  
  181. static int load_protected_program(char *filename)
  182. {
  183.     GNUOUT aout_hdr;
  184.     DWORD sizetext, sizedata, sizestack;
  185.     DWORD headoff;
  186.     int fhandle;
  187.  
  188.     if ((fhandle = dos_open(filename, DO_RDONLY | DO_DENYWR)) == -1) {
  189.     error("open rsx32 error\r\n$");
  190.     return 1;
  191.     }
  192.  
  193.     headoff = 0;
  194.     skip_exe_hdr(fhandle, &headoff);
  195.  
  196.     /* read gnu aout header */
  197.     dos_read(fhandle, &aout_hdr, sizeof(aout_hdr));
  198.  
  199.     /* test header */
  200.     if ((WORD) aout_hdr.a_info != 0x10b) {
  201.     error("illegal a.out header\r\n$");
  202.     dos_close(fhandle);
  203.     return 2;
  204.     }
  205.  
  206.     sizetext = (aout_hdr.a_text + SEGMENT_SIZE - 1L) & ~(SEGMENT_SIZE - 1L);
  207.     sizedata = aout_hdr.a_data + ((aout_hdr.a_bss + 4095L) & ~4095L);
  208.     sizestack = 64 * 1024L;
  209.  
  210.     info.text_start = N_TXTADDR(x);
  211.     info.data_start = info.text_start + sizetext;
  212.     info.bss_start = info.data_start + aout_hdr.a_data;
  213.  
  214.     info.membytes = sizestack + sizetext + sizedata;
  215.     info.entry = aout_hdr.a_entry;
  216.     info.init_brk = info.data_start + sizedata;
  217.     stackp32 = info.text_start - 4L;
  218.  
  219.     /* MEMORY per DOS besorgen */
  220.     if (!DosReallocParagraph(_psp, (WORD)(info.membytes>>4))) {
  221.     error("realloc memory error\r\n$");
  222.     return 3;
  223.     }
  224.     segm = _psp;
  225.  
  226.     info.memaddress = (DWORD)segm << 4;
  227.  
  228.     /* read in code */
  229.     dos_lseek(fhandle, headoff + N_TXTOFF(aout_hdr), SEEK_SET);
  230.     if (read_in(fhandle, info.memaddress + info.text_start, aout_hdr.a_text))
  231.     return 1;
  232.  
  233.     /* read in data */
  234.     dos_lseek(fhandle, headoff + N_DATOFF(aout_hdr), SEEK_SET);
  235.     if (read_in(fhandle, info.memaddress + info.data_start, aout_hdr.a_data))
  236.     return 1;
  237.  
  238.     dos_close(fhandle);
  239.  
  240.     /* zero bss segment */
  241.     if (aout_hdr.a_bss) {
  242.     FP_SEG(extdata) = (WORD) ((info.memaddress + info.bss_start) >> 4);
  243.     FP_OFF(extdata) = (WORD) ((info.memaddress + info.bss_start) & 0xFL);
  244.     far_bzero(extdata, (WORD) aout_hdr.a_bss);
  245.     }
  246.     return 0;
  247. }
  248.  
  249. static int real_to_protected(WORD mode)
  250. {
  251.     static WORD DPMIdata_para_needed;
  252.     static WORD DPMIdata_segm_address;
  253.     WORD DPMIflags, DPMIversion;
  254.     BYTE processor;
  255.     DWORD PM_jump;        /* switch to protmode jump */
  256.  
  257.     if (GetDpmiEntryPoint(&PM_jump, &DPMIdata_para_needed,
  258.               &DPMIflags, &DPMIversion, &processor)) {
  259.     error("No DPMI-host found!\r\n$");
  260.     return -1;
  261.     }
  262.     if (mode == 1 && !(DPMIflags & 1)) {
  263.     error("32bit programs not supported by Host\r\n$");
  264.     return -1;
  265.     }
  266.     if (DPMIdata_para_needed) { /* get DPMI ring 0 stack */
  267.     DPMIdata_segm_address = GetDpmiHostParagraph(DPMIdata_para_needed);
  268.     if (!DPMIdata_segm_address) {
  269.         error("Can't alloc memory for the DPMI-host-stack\r\n$");
  270.         return -1;
  271.     }
  272.     }
  273.     if (DpmiEnterProtectedMode(PM_jump, mode, DPMIdata_segm_address)) {
  274.     error("can't switch to Protected Mode\r\n$");
  275.     return -1;
  276.     }
  277.  
  278.     if (DPMIdata_para_needed)
  279.     LockLinRegion((DWORD) DPMIdata_segm_address << 4,
  280.               (DWORD) DPMIdata_para_needed << 4);
  281.  
  282.     /* Now we are in Protected Mode */
  283.     info.code16sel = GetCS();
  284.     info.data16sel = GetDS();
  285.  
  286.     return 0;
  287. }
  288.  
  289. static void init_descriptors()
  290. {
  291.     AllocLDT(2, &(code32sel));
  292.     data32sel = code32sel + SelInc();
  293.  
  294.     SetBaseAddress(code32sel, info.memaddress);
  295.     SetBaseAddress(data32sel, info.memaddress);
  296.     SetAccess(code32sel, APP_CODE_SEL, DEFAULT_BIT | GRANULAR_BIT);
  297.     SetAccess(data32sel, APP_DATA_SEL, DEFAULT_BIT | GRANULAR_BIT);
  298.     SetLimit(code32sel, info.membytes - 1);
  299.     SetLimit(data32sel, info.membytes - 1);
  300. }
  301.  
  302. static void get_cmdline_from_psp(unsigned psp_segm)
  303. {
  304.     int z, env_seg;
  305.     char far *cmdl;
  306.  
  307.     /* get envoronment segment from PSP */
  308.     env_seg = *(int far *) (((DWORD) psp_segm << 16) | 0x2c);
  309.  
  310.     /* build far pointer to environment */
  311.     cmdl = (char far *) ((DWORD) env_seg << 16);
  312.  
  313.     /* save environment pointer */
  314.     env_str = (char far *) ((DWORD) env_seg << 16);
  315.  
  316.     /* skip env-strings ; last has two 0-bytes */
  317.     for (;;) {
  318.     if (*cmdl == '\0' && *(cmdl+1) == '\0')
  319.         break;
  320.     cmdl++;
  321.     }
  322.  
  323.     cmdl += 4;
  324.     /* copy arg0 */
  325.     for (z = 0; z < sizeof(cline); z++) {
  326.     cline[z] = *cmdl;
  327.     if (cline[z] == '\0')
  328.         break;
  329.     cmdl++;
  330.     }
  331.     cline[z++] = ' ';
  332.  
  333.     /* build cmdline far pointer from PSP */
  334.     cmdl = (char far *) ((DWORD) psp_segm << 16 | 0x81);
  335.  
  336.     /* copy arg1,arg2,... */
  337.     for ( ; z < sizeof(cline) ; z++) {
  338.     cline[z] = *cmdl;
  339.     if (cline[z] == 13)
  340.         break;
  341.     cmdl++;
  342.     }
  343.     cline[z] = '\0';
  344. }
  345.  
  346. static void build_args(int *argn, char ***argvp, int stub_opt)
  347. {
  348.     static char extra[] = "!RSX";
  349.     static char *argvec[20];
  350.  
  351.     int argc, src, dst, bs, quote;
  352.     char *q;
  353.  
  354.     argc = 0;
  355.     dst = src = 0;
  356.  
  357.     if (stub_opt)
  358.     argvec[argc++] = extra;
  359.  
  360.     while (cline[src] == ' ' || cline[src] == '\t' || cline[src] == '\n')
  361.     ++src;
  362.     do {
  363.     if (cline[src] == 0)
  364.         q = NULL;
  365.     else {
  366.         q = cline + dst;
  367.         bs = 0;
  368.         quote = 0;
  369.         for (;;) {
  370.         if (cline[src] == '"') {
  371.             while (bs >= 2) {
  372.             cline[dst++] = '\\';
  373.             bs -= 2;
  374.             }
  375.             if (bs & 1)
  376.             cline[dst++] = '"';
  377.             else
  378.             quote = !quote;
  379.             bs = 0;
  380.         } else if (cline[src] == '\\')
  381.             ++bs;
  382.         else {
  383.             while (bs != 0) {
  384.             cline[dst++] = '\\';
  385.             --bs;
  386.             }
  387.             if (cline[src] == 0 ||
  388.             ((cline[src] == ' ' || cline[src] == '\t') && !quote))
  389.             break;
  390.             cline[dst++] = cline[src];
  391.         }
  392.         ++src;
  393.         }
  394.         while (cline[src] == ' ' || cline[src] == '\t'
  395.            || cline[src] == '\n')
  396.         ++src;
  397.         cline[dst++] = 0;
  398.     }
  399.     argvec[argc++] = q;
  400.     } while (q != NULL);
  401.  
  402.     *argn = argc - 1;
  403.     *argvp = (char **) &(argvec[0]);
  404. }
  405.  
  406. int main(void)
  407. {
  408.     int argc;
  409.     char **argv;
  410.     char exe_name[130];
  411.  
  412.     get_cmdline_from_psp(_psp);
  413.     build_args(&argc, &argv, 0);
  414.     my_strcpy(exe_name, argv[0]);
  415.  
  416.     if (argc == 2 && argv[1][0]=='-' && argv[1][1] == '/' && argv[1][6] == '/') {
  417.     unsigned newpsp;
  418.     int i;
  419.     char s;
  420.     newpsp = 0;
  421.     for ( i=2 ; i<=5 ; i++) {
  422.         s = argv[1][i];
  423.         if (s >= 'A')
  424.         s -= ('A' - 10);
  425.         else
  426.         s -= '0';
  427.         newpsp <<= 4;
  428.         newpsp |= s;
  429.     }
  430.     get_cmdline_from_psp(newpsp);
  431.     build_args(&argc, &argv, 1);
  432.     }
  433.  
  434.     if (argc > 7 && argv[1][0]=='!' && argv[1][1] == 'p' && argv[1][5] == 'y') {
  435.     unsigned newpsp;
  436.     int i;
  437.     char s;
  438.     newpsp = 0;
  439.     for ( i=0 ; i<=3 ; i++) {
  440.         s = argv[7][i];
  441.         if (s >= 'a')
  442.         s -= ('a' - 10);
  443.         else if (s >= 'A')
  444.         s -= ('A' - 10);
  445.         else
  446.         s -= '0';
  447.         newpsp <<= 4;
  448.         newpsp |= s;
  449.     }
  450.     get_cmdline_from_psp(newpsp);
  451.     build_args(&argc, &argv, 1);
  452.     }
  453.  
  454.     if (load_protected_program(exe_name))
  455.     return(1);
  456.  
  457.     if (argvenv(argc, argv))
  458.     return (1);
  459.  
  460.     if (real_to_protected(1))
  461.     return (1);
  462.  
  463.     init_descriptors();
  464.     jmp_to_user();
  465.     return 0;
  466. }
  467.